#include <iostream>
#include <vector>
#include <cstdlib>
#include "Specimen.hpp"
#include "ProportionalEnv.hpp"
#include "TournamentEnv.hpp"
#include "AckleyFunction.hpp"
#include "EvolutionaryException.hpp"
#include "GeemFunction.hpp"
#include "RosenbrockFunction.hpp"
#include "HimmelblauFunction.hpp"
#include "GoldsteinPriceFunction.hpp"
#include "RastiginFunction.hpp"
#include "parserCalc.hpp"

using std::cout;
using std::cerr;
using std::endl;

/*
Gene linearScaling(const Gene &value)
{
  Gene scale=10;
  return value*scale;
}

Gene exponentialScaling(const Gene &value)
{
  return exp(value);
}
*/

int main(int argc,char** argv)
{

  /* パーサのテスト */
  parserCalc newParser;
  cerr<<"powinno wyjsc 7 dla podanych danych\n";
  newParser.writeExpression("x^2+y");
  Specimen kin;
  kin.init(2);
  kin[0]=-3;
  kin[1]=-2;
  newParser(kin);
  //newParser.setVariables(kin[0]);

  //cerr << "kso\n\n";
  //newParser.writeExpression("x^2");
  //float zlo = newParser.evalExpression();

  cerr << "kso ho ho\n\n";

  //Test klasy proportional env
		
  {
    std::vector<Gene> max,min;
		
    max.push_back(5);
    max.push_back(10);
    min.push_back(0);
    min.push_back(0);
		
		
		
    {
      TournamentEnv propEnv;
      //AckleyFunction ackley(2);
      HimmelblauFunction function;		
			
      try
	{
	  //	  propEnv.setScalingFunction(exponentialScaling);
	  propEnv.setIfReturning(true);
	  propEnv.setMaxPopulation(50);
				
	  //jesli nie ustawione s ograniczenia na przyrost x i y, to nie sa brane pod uwag
	  //propEnv.setFitnessMinChange(0.0000001);
	  //propEnv.setCoordinatesMinChange(0.0000001);
	  // jak na razie strasznie szybko zbiega
				
	  propEnv.setMaxIterations(5000);
	  propEnv.setMutationProbability(0.15);
	  propEnv.setAlgebraicCrossoverProportion(0.3);
	  propEnv.setCrossoverProbability(0.5);
	  propEnv.setDimensionality(function.getDimensionality());
	  propEnv.setMaxX(max);
	  propEnv.setMinX(min);
				
	  propEnv.prepare(function);
				
	  //	  propEnv.makeGeneration(function);
	}
      catch(EvolutionaryException &ex)
	{
	  cout<<ex.what()<<endl;
	}
      std::vector<Specimen> children=propEnv.getChildren();
      /*
	for(unsigned i=0;i<children.size();++i)
	{
	for(unsigned j=0;j<children[i].getDimensions();++j)
	{
	cout<<children[i][j]<<" ";
	}
	cout<<" fitness: "<<children[i].getFitness()<<endl;
	}
      */
      try
	{
	  Specimen theBestOne=propEnv.search(function);
	  std::vector<Specimen> children=propEnv.getChildren();
	  /*
	    for(unsigned i=0;i<children.size();++i)
	    {
	    for(unsigned j=0;j<children[i].getDimensions();++j)
	    {
	    cout<<children[i][j]<<" ";
	    }
	    cout<<" fitness: "<<children[i].getFitness()<<endl;
	    }
	  */
	  cout<<endl<<"the best one"<<endl;
	  for(unsigned j=0;j<theBestOne.getDimensions();++j)
	    {
	      cout<<theBestOne[j]<<" ";
	    }
	  cout<<" fitness: "<<theBestOne.getFitness()<<endl;
				
	}
      catch(EvolutionaryException &ex)
	{
	  cout<<ex.what()<<endl;
	}
			
    }
  }

#if defined(WIN32) || defined(_WIN32)
  system("pause");
#endif
  return EXIT_SUCCESS;
}
